package com.liurong.quartz.util;

import java.util.Map;
import java.util.Set;

import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.liurong.quartz.util.entity.JobEntity;
import com.liurong.util.redis.RedisTemplate;

/**
 * job从机监控线程：监控主线程是否存在，如果存在则继续监控，如果不存在选举自己成为主机线程
 * 
 * @author liurong
 *
 */
public class ClusterThread extends Thread {
	private static final Logger logger = LoggerFactory.getLogger(ClusterThread.class);

	/**
	 * 判断该机器是否为主机
	 */
	private boolean isMain = false;

	/**
	 * 定时任务心跳redis key
	 */
	public static final String JOB_HEART_BEAT_REDIS_KEY = "job_heart_beat_redis_key";

	private Map<String, JobEntity> jobNameMap;
	private RedisTemplate redisTemplate;
	private String localIpStr;

	public ClusterThread(Map<String, JobEntity> jobNameMap, RedisTemplate redisTemplate, String localIpStr) {
		this.jobNameMap = jobNameMap;
		this.redisTemplate = redisTemplate;
		this.localIpStr = localIpStr;
	}

	public void setMain(boolean isMain) {
		this.isMain = isMain;
	}

	@Override
	public void run() {
		logger.info("ClusterThread启动成功！");
		String heartbeatValue = null;
		MasterThread masterThread = null;
		Set<String> jobNameKey = jobNameMap.keySet();
		JobEntity jobEntity = null;
		while (!JobStartConfig.isStop) {
			try {
				heartbeatValue = redisTemplate.get("jedis_lock_" + JOB_HEART_BEAT_REDIS_KEY);
				if (StringUtils.isEmpty(heartbeatValue)) {
					// 如果获取到锁，说明本机已经成为了主机
					if (redisTemplate.lock(JOB_HEART_BEAT_REDIS_KEY, localIpStr, 1000 * 30, 0)) {
						isMain = true;
						masterThread = new MasterThread(this, redisTemplate, localIpStr);
						masterThread.setName("masterThread");
						masterThread.start();
					}
				}
				for (String jobName : jobNameKey) {
					jobEntity = jobNameMap.get(jobName);
					// 如果是主机就全部启动
					if (isMain) {
						jobEntity.setIsStart(1);
						JobStartConfig.scheduler.resumeJob(new JobKey(jobEntity.getJobName(), Scheduler.DEFAULT_GROUP));
					} else {// 如果是丛机只启动支持分布式的job
						if (jobEntity.isDistribute()) {
							jobEntity.setIsStart(1);
						} else {
							try {
								JobStartConfig.scheduler
										.pauseJob(new JobKey(jobEntity.getJobName(), Scheduler.DEFAULT_GROUP));
							} catch (SchedulerException e) {
								logger.info("暂停jobName={}时抛出异常：", jobEntity.getJobName(), e);
							}
						}
					}
				}

				if (isMain) {
					logger.info("我是主机");
				} else {
					logger.info("我是丛机");
				}

				JobStartConfig.scheduler.start();

				this.setJobMapToRedis();

				Thread.sleep(1000 * 40);

			} catch (Exception e) { // 防御性容错
				logger.error("ClusterThread error:", e);
			}
		}
	}

	/**
	 * 将map放入redis中
	 */
	private void setJobMapToRedis() {
		String jobNameMapStr = JSON.toJSONString(jobNameMap);
		logger.info("将job内容放入redis中  jobNameMapStr={}", jobNameMapStr);
		StringBuilder key = new StringBuilder();
		key.append("jobNameMapStr");
		key.append(":");
		key.append(localIpStr);
		boolean result = redisTemplate.lock(key.toString(), jobNameMapStr, 1000 * 30, 0);
		logger.info("将job内容放入redis中返回值   result={}", result);
	}
}
